package com.wisnews.config.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.wisnews.pojo.sec.entity.ShiroRequestController;
import com.wisnews.service.sec.IShiroRequestControllerService;
import com.wisnews.util.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {

	@Autowired
	private IShiroRequestControllerService shiroRequestControllerService;

	// ShiroFilterFactoryBean //工厂对象 :第三步
	@Bean
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(
			@Qualifier("mySecurity") DefaultWebSecurityManager security) {
		ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
		// 设置安全管理器
		bean.setSecurityManager(security);
		// 添加shiro的内置过滤器
		/*
		 * anon : 无需认证就可以访问 authc : 必须认证了才能访问 user : 必须拥有 记住我 功能才能访问 perms :
		 * 拥有对某个资源的权限才能访问 role : 拥有某个角色权限才能访问
		 */
		// 拦截
		Map<String, String> filterMap = new LinkedHashMap<>();

		log.info("==>getShiroFilterFactoryBean读入请求权限信息开始");
		List<ShiroRequestController> list = shiroRequestControllerService.list();

		list.forEach(shiroRequestController -> {
			if ("anon".equals(shiroRequestController.getNeedPermission()) ||
					"authc".equals(shiroRequestController.getNeedPermission())){
				filterMap.put(shiroRequestController.getReqPath(),shiroRequestController.getNeedPermission());
			}else {
				String[] str = shiroRequestController.getNeedPermission().split(",");
				if (ObjectUtils.isNotNull(str)){
					for (int i = 0; i < str.length; i++) {
						filterMap.put(shiroRequestController.getReqPath(),"perms[" + str[i] + "]");

					}
				}
			}
		});

		bean.setFilterChainDefinitionMap(filterMap);
		// 设置登录请求
		bean.setLoginUrl("/login.html");
		// 设置未授权请求
		bean.setUnauthorizedUrl("/noauth.html");
		return bean;
	}

	// DafaultWebSecurityManager //管理对象 :第二步
	@Bean(name = "mySecurity")
	public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm,@Qualifier("memberRealm") MemberRealm memberRealm) {
		DefaultWebSecurityManager security = new DefaultWebSecurityManager();

		//采用多realm认证,默认使用  AtLeastOneSuccessfulStrategy：至少有一个Realm验证成功就登录成功（默认策略）
		//取消前台用户认证，需要使用时打开
		//List<Realm> realms = Arrays.asList(userRealm, memberRealm);
		List<Realm> realms = Arrays.asList(userRealm);

		//关联多个realm
		security.setRealms(realms);
		return security;
	}

	// realm 对象 需要自定义类 :第一步
	@Bean("userRealm")
	public UserRealm userRealm() {

		UserRealm userRealm = new UserRealm();

		//创建凭证匹配器
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		//设置加密算法名称
		credentialsMatcher.setHashAlgorithmName("MD5");
		//设置hash迭代次数
		credentialsMatcher.setHashIterations(Constants.SYS_CODE.PSWD_DEGREE);
		//覆盖默认凭证匹配器
		userRealm.setCredentialsMatcher(credentialsMatcher);

		//关联缓存管理器
		userRealm.setCacheManager(redisCacheManager());
		//开启全局缓存
		userRealm.setCachingEnabled(true);
		//认证缓存
		userRealm.setAuthenticationCachingEnabled(true);
		userRealm.setAuthenticationCacheName("authenticationCache");
		//授权缓存
		userRealm.setAuthorizationCachingEnabled(true);
		userRealm.setAuthorizationCacheName("authorizationCache");

		return userRealm;
	}

	@Bean
	public MemberRealm memberRealm(){
		MemberRealm memberRealm = new MemberRealm();

		//创建凭证匹配器
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		//设置加密算法名称
		credentialsMatcher.setHashAlgorithmName("MD5");

		memberRealm.setCredentialsMatcher(credentialsMatcher);

		//关联缓存管理器
		memberRealm.setCacheManager(redisCacheManager());
		//开启全局缓存
		memberRealm.setCachingEnabled(true);
		//认证缓存
		memberRealm.setAuthenticationCachingEnabled(true);
		memberRealm.setAuthenticationCacheName("member-authenticationCache");
		//授权缓存
		memberRealm.setAuthorizationCachingEnabled(true);
		memberRealm.setAuthorizationCacheName("member-authorizationCache");

		return memberRealm;
	}

	// 整合ShiroDialect:用来整合 shiro thymeleaf
	@Bean
	public ShiroDialect getShiroDialect() {
		return new ShiroDialect();
	}


	//配置shiro整合redis
	@Bean
	public RedisCacheManager redisCacheManager(){
		return new RedisCacheManager();
	}

	@Bean
	public RedisCache redisCache(){
		return new RedisCache();
	}

}
